package srv

import (
	"errors"
	"fmt"
	"go-init/dao"
	"reflect"
	"strings"
)

var (
	Tag       = "gorm"
	TableName = "TableName"
	separate  = ";"
	pkindex   = separate + "pk"
	empthv    = reflect.Value{}
)

func InsertOperateRecord(operateid, userid, operatetableid, dataid interface{}, remark string) (err error) {
	_, err = dao.Exec("insert into user_operate_record (user_operate_id,user_id,user_operate_table_id,remark,data_id,"+
		"create_time) values (?,?,?,?,?,now())", operateid, userid, operatetableid, remark, dataid)
	return
}
func InsertOperateRecordSimple(o, n interface{}, userid int) (err error) {
	ot := reflect.TypeOf(o)
	ov := reflect.ValueOf(o)
	nt := reflect.TypeOf(o)
	nv := reflect.ValueOf(o)
	remark, err := userOperateRemark(ot, ov, nt, nv)
	if err != nil {
		return
	}
	dataid := getdataid(nt, nv)
	operateid := 1
	insert := getpk(ot, ov)
	if !insert {
		operateid = 3
	}
	tableid := gettableid(getTableName(ot, ov))
	err = InsertOperateRecord(operateid, userid, tableid, dataid, remark)
	return
}

func gettableid(tablename string) int {
	qs := dao.NewQs()
	qs.Add("a.t_name=?", tablename)
	t, err := dao.UserOperateTableo(qs)
	if err != nil {
		return 0
	}
	return t.Id
}

func getpk(t reflect.Type, v reflect.Value) (insert bool) {
	for i := 0; i < t.NumField(); i++ {
		vs := t.Field(i).Tag.Get(Tag)
		if strings.Index(vs, pkindex) > -1 {
			if v.Field(i).IsZero() {
				insert = true
			}
			break
		}
	}
	return
}

func getdataid(t reflect.Type, v reflect.Value) (dataid int64) {
	for i := 0; i < t.NumField(); i++ {
		vs := t.Field(i).Tag.Get(Tag)
		if strings.Index(vs, pkindex) > -1 {
			dataid = v.Field(i).Int()
			break
		}
	}
	return
}

func UserOperateRemark(o, n interface{}) (remark string, err error) {
	ot := reflect.TypeOf(o)
	ov := reflect.ValueOf(o)
	nt := reflect.TypeOf(n)
	nv := reflect.ValueOf(n)
	if ot.Name() != nt.Name() {
		err = errors.New("两个数据不匹配")
		return
	}
	remark, err = userOperateRemark(ot, ov, nt, nv)
	return
}

func userOperateRemark(ot reflect.Type, ov reflect.Value, nt reflect.Type, nv reflect.Value) (remark string, err error) {
	if ot.Name() != nt.Name() {
		err = errors.New("两个数据不匹配")
		return
	}
	insert := getpk(ot, ov)

	var ss []string
	for i := 0; i < ot.NumField(); i++ {
		vs := ot.Field(i).Tag.Get(Tag)
		if vs != "" {
			ovv := ov.Field(i).Interface()
			nvv := nv.Field(i).Interface()
			if ot.Field(i).Type.String() == "time.Time" {
				ovvs := fmt.Sprint(ovv)
				nvvs := fmt.Sprint(nvv)
				if ovvs[:19] != nvvs[:19] {
					if insert {
						ss = append(ss, fmt.Sprintf("%s : %v", vs, nvvs[:19]))
					} else {
						ss = append(ss, fmt.Sprintf("%s : %v -> %v", vs, ovvs[:19], nvvs[:19]))
					}
				}
			} else {
				if ovv != nvv {
					if insert {
						ss = append(ss, fmt.Sprintf("%s : %v", vs, nvv))
					} else {
						ss = append(ss, fmt.Sprintf("%s : %v -> %v", vs, ovv, nvv))
					}
				}
			}
		}
	}
	remark = strings.Join(ss, "\n")
	return
}

func getTableName(t reflect.Type, v reflect.Value) string {
	tablename := t.Name()
	m := v.MethodByName(TableName)
	if m != empthv {
		tablename = m.Call([]reflect.Value{})[0].String()
	}
	return tablename
}
